#include <assert.h>

#include "vec4.h"

namespace TG
{
	float& vec4::operator[](size_t i)
	{
		assert(i < 4);
		return (&x)[i];
	}

	const float& vec4::operator[](size_t i) const
	{
		assert(i < 4);
		return (&x)[i];
	}

	vec4& vec4::operator=(const vec4 &v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
		this->w = v.w;
		return *this;
	}

	vec4& vec4::operator=(const vec3 &v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
		this->w = 1;
		return *this;
	}

	template<typename U>
	vec4& vec4::operator+=(const U &s)
	{
		this->x += float(s);
		this->y += float(s);
		this->z += float(s);
		this->w += float(s);
		return *this;
	}

	vec4& vec4::operator+=(const vec4 &v)
	{
		this->x += v.x;
		this->y += v.y;
		this->z += v.z;
		this->w += v.w;
		return *this;
	}

	template<typename U>
	vec4& vec4::operator-=(const U &s)
	{
		this->x -= float(s);
		this->y -= float(s);
		this->z -= float(s);
		this->w -= float(s);
		return *this;
	}

	vec4& vec4::operator-=(const vec4 &v)
	{
		this->x -= v.x;
		this->y -= v.y;
		this->z -= v.z;
		this->w -= v.w;
		return *this;
	}

	template <typename U>
	vec4& vec4::operator*= (const U &s)
	{
		this->x *= float(s);
		this->y *= float(s);
		this->z *= float(s);
		this->w *= float(s);
		return *this;
	}

	vec4& vec4::operator*=(const vec4 &v)
	{
		this->x *= float(v.x);
		this->y *= float(v.y);
		this->z *= float(v.z);
		this->w *= float(v.w);
		return *this;
	}

	template <typename U>
	vec4& vec4::operator/=(const U &s)
	{
		this->x /= float(s);
		this->y /= float(s);
		this->z /= float(s);
		this->w /= float(s);
		return *this;
	}

	vec4& vec4::operator/=(const vec4 &v)
	{
		this->x /= v.x;
		this->y /= v.y;
		this->z /= v.z;
		this->w /= v.w;
		return *this;
	}

	vec4& vec4::operator++()
	{
		++this->x;
		++this->y;
		++this->z;
		++this->w;
		return *this;
	}

	vec4& vec4::operator--()
	{
		--this->x;
		--this->y;
		--this->z;
		--this->w;
		return *this;
	}

	vec4 vec4::operator+(const vec4 &v0)
	{
		return vec4(v0.x + this->x, v0.y + this->y, v0.z + this->z, v0.w + this->w);
	}

	vec4 vec4::operator/(float s)
	{
		return vec4(this->x / s, this->y / s, this->z / s, this->w / s);
	}

	vec4 vec4::operator*(float s)
	{
		return vec4(this->x * s, this->y * s, this->z * s, this->w * s);
	}

	vec4 vec4::operator+(float s)
	{
		return vec4(this->x + s, this->y + s, this->z + s, this->w + s);
	}

	vec4::operator vec3() {
		return vec3(x, y, z);
	}
}